package forum;

import java.awt.geom.*;

import processing.core.PApplet;


public class MouseOver extends PApplet {

	Shape selected = null;

	int nbr = 5;
	Shape[] shapes = new Shape[nbr];

	public void setup(){
		size(400,400);
		cursor(CROSS);
		for(int i = 0; i < shapes.length; i++){
			float x = 50 + random(width - 100);
			float y = 50 + random(height - 100);
			float w = random(20, 50);
			float h = random(20,50);
			float a = random(TWO_PI);
			shapes[i] = new Rectangle(this,x,y,w,h,a);

		}
	}

	public void mouseMoved(){
		selected = null;
		for(int i = 0; i < shapes.length; i++){
			if(shapes[i].isOver(mouseX, mouseY)){
				selected = shapes[i];
				break; // exit for loop
			}
		}		
	}

	public void draw(){
		background(255);
		for(int i = 0; i < shapes.length; i++)
			shapes[i].display(selected);
	}

	public static abstract class Shape {
		protected PApplet app;

		// These variables are used to calculate whether a
		// point is over the shape. They are created once
		// and reused for efficiency reasons.
		protected AffineTransform aff = new AffineTransform();
		protected double[] temp = new double[2];
		protected float ox, oy;
		// ------------------------------------------------

		protected float x, y;		// position
		protected float rot; 		// angle rotated in radians

		protected int strokeColor;
		protected int fillColor;
		protected float strokeWeight;

		public Shape(PApplet app, float x, float y, float rot){
			this.app = app;
			this.x = x;
			this.y = y;
			this.rot = rot;
			strokeColor = app.color(100,100,200);
			fillColor = app.color(240,240,0);
			strokeWeight = 2.0f;
		}

		public abstract boolean isOver(float px, float py);

		public abstract void display(Shape selected);

	}

	public static class Rectangle extends Shape {

		private float w, h;

		public Rectangle(PApplet app, float x, float y, float w, float h, float rot) {
			super(app, x, y, rot);
			this.w = w;
			this.h = h;
		}

		@Override
		public boolean isOver(float px, float py) {
			// Use setToTranslation so that it replaces previous
			// transformation
			aff.setToTranslation(x, y);
			aff.rotate(rot);
			// Store coordinates of interest in array for transforming
			temp[0] = px; temp[1] = py;
			try {
				// Reverse the applied transformation to the coordinates 
				aff.inverseTransform(temp, 0, temp, 0, 1);
				ox = (float) temp[0];
				oy = (float) temp[1];
			} catch (NoninvertibleTransformException e) {
				// Unable to invert point so not over shape
				return false;
			}
			// Is [ox,oy] over the un-transformed shape
			if(ox > -w/2 && ox < w/2 && oy > -h/2 && oy < h/2)
				return true;
			else
				return false;
		}	

		public void display(Shape selected) {
			app.pushStyle();
			app.pushMatrix();

			app.rectMode(PApplet.CENTER);
			app.fill(fillColor);
			app.stroke(strokeColor);
			app.strokeWeight(strokeWeight);

			app.translate(x, y);
			app.rotate(rot);
			// Draw the shape
			app.rect(0, 0, w, h);

			// See if this is the selected shape
			// if it is draw a red box round it
			if(this == selected){
				app.stroke(255,0,0);
				app.strokeWeight(3);;
				app.noFill();
				app.rect(0, 0, w, h);
			}

			app.popMatrix();
			app.popStyle();
		}

	}

}